﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace Admx_Generator
{
    public class SupportedOnList
    {
        private List<SupportedOnItem> _supportedOnItems = new List<SupportedOnItem>();

        /// <summary>
        /// Create an instance of SupportedOnList populated with supportedOn items found in the Admx file
        /// </summary>
        /// <param name="admxFilePath">An instance of SupportedOnList</param>
        public SupportedOnList(string admxFilePath)
        {
            this._supportedOnItems = this.ExtractSupportedOnItems(admxFilePath);
        }

        #region (Internal Properties)
        
        /// <summary>
        /// List of all SupportedOn Items found in the AdmxFile.
        /// </summary>
        public List<SupportedOnItem> SupportedonItems { get { return this._supportedOnItems; } }

        #endregion (Internal Properties)

        public SupportedOnItem SupportedOnItem
        {
            get
            {
                throw new System.NotImplementedException();
            }
            set
            {
            }
        }

        #region (Private Methods)

        /// <summary>
        /// Extract all SupportedOn item from an Admx file
        /// </summary>
        /// <param name="admxFilePath">Full path to the Admx file</param>
        /// <returns>A List of <see cref="SupportedOnItem"></see> extracted from the Admx file. Returns an empty list if nothing found</returns>
        public List<SupportedOnItem> ExtractSupportedOnItems(string admxFilePath)
        {
            List<SupportedOnItem> items = new List<SupportedOnItem>();
            try
            {
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(admxFilePath);

                if (fileInfo.Exists)
                {
                    Dictionary<string, string> stringTable = this.GetStringTable(fileInfo);

                    XDocument xDoc = XDocument.Load(admxFilePath);
                    XNamespace ns = xDoc.Root.GetDefaultNamespace();
                    XElement target = xDoc.Descendants(ns + "target").ToList<XElement>()[0];
                    XAttribute namespaceAttribute = target.Attribute("namespace");
                    XAttribute prefixAttribute = target.Attribute("prefix");
                    Namespace supportedOnNamespace = new Admx_Generator.Namespace(namespaceAttribute.Value, prefixAttribute.Value);

                    List<XElement> definitionElements = xDoc.Descendants(ns + "definition").ToList<XElement>();
                    foreach (XElement definition in definitionElements)
                    {
                        SupportedOnItem item = new SupportedOnItem(supportedOnNamespace);
                        item.NameAttribute = definition.Attribute("name").Value;
                        if (stringTable.ContainsKey(this.GetDisplayNameID(definition.Attribute("displayName").Value)))
                            item.LocalizedDisplayName = stringTable[this.GetDisplayNameID(definition.Attribute("displayName").Value)];
                        else
                            item.LocalizedDisplayName = definition.Attribute("displayName").Value;

                        items.Add(item);
                    }
                }
            }
            catch (Exception) { }

            return items;
        }

        /// <summary>
        /// Returns a dictionary of StringTableID and StringTableValue from an Admx file
        /// </summary>
        /// <param name="admxFilePath">Full path to an Admx file</param>
        /// <returns>A dictionary with StringTableID as key, and StringTableValue as values</returns>
        public Dictionary<string, string> GetStringTable(System.IO.FileInfo admxFilePath)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();

            try
            {
                string admxFolder = admxFilePath.DirectoryName;
                string admxFilename = admxFilePath.Name;
                string admlFilename = this.GetAdmlFile(admxFolder, admxFilename);

                XDocument xDoc = XDocument.Load(admlFilename);
                XNamespace ns = xDoc.Root.GetDefaultNamespace();
                List<XElement> strings = xDoc.Descendants(ns + "string").ToList<XElement>();

                foreach (XElement element in strings)
                {
                    result.Add(element.Attribute("id").Value, element.Value);
                }

            }
            catch (Exception) { }

            return result;
        }

        /// <summary>
        /// Get the full path to the Adml file associated with an Admx file, for the current culture.
        /// </summary>
        /// <param name="admxFolder">Folder where the Admx file is located</param>
        /// <param name="admxFilename">Name of the Admx file</param>
        /// <returns>Full path to the Adml file.</returns>
        public string GetAdmlFile(string admxFolder, string admxFilename)
        {
            string currentCulture = System.Globalization.CultureInfo.CurrentCulture.Name;
            string admlFilename = admxFilename.Substring(0, admxFilename.LastIndexOf('.')) + ".adml";

            string admlFileinCurrentCultureFolder = System.IO.Path.Combine(admxFolder + "\\" + currentCulture, admlFilename);
            if (System.IO.File.Exists(admlFileinCurrentCultureFolder))
                return admlFileinCurrentCultureFolder;
            else
            {
                System.IO.DirectoryInfo rootFolder = new System.IO.DirectoryInfo(admxFolder);
                foreach (System.IO.DirectoryInfo subfolder in rootFolder.GetDirectories())
                {
                    string admlFileInSubFolder = System.IO.Path.Combine(admxFolder + "\\" + subfolder.Name, admlFilename);
                    if (System.IO.File.Exists(admlFileInSubFolder))
                        return admlFileInSubFolder;
                }
            }

            return String.Empty;
        }
        
        /// <summary>
        /// Extract the ID from a Admx StringId formated text (eg : $(string.ID))
        /// </summary>
        /// <param name="str">A Admx StringID formated text like '$(string.ID)'</param>
        /// <returns>Returns the ID extracted from the text, or StringEmpty if no ID were found</returns>
        public string GetDisplayNameID(string str)
        {
            if (!String.IsNullOrEmpty(str) && str.StartsWith("$(string.", StringComparison.CurrentCultureIgnoreCase))
                return str.Substring("$(string.".Length, str.Length - "$(string.".Length - 1);

            return String.Empty;
        }

        #endregion (Private Methods)
    }
}
